package me.ingxin.android.router.route

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import me.ingxin.android.router.base.DataExtras
import me.ingxin.android.router.utils.Logger
import me.ingxin.android.router.utils.getFragmentActivity

/**
 * Created by ingxin on 2022/4/18
 * @param uri 路由地址
 */
class Request internal constructor(uri: Uri) : DataExtras<Request>() {

    var uri: Uri
        private set

    init {
        this.uri = uri
    }

    /**转场动画*/
    internal var options: ActivityOptionsCompat? = null
        private set

    /**是否可以重定向*/
    @JvmField
    internal var canRedirect = true

    /**Intent flags*/
    internal var flags: Int = 0
        private set

    /**Intent action*/
    internal var action: String? = null
        private set

    /**路由回调*/
    internal var routeCallback: RouteCallback? = null
        private set

    /**activity数据回传*/
    internal var activityResultCallback: ActivityResultCallback<ActivityResult>? = null
        private set

    /**
     * 重定向到一个新的路由
     * <p>
     *     重定向只能在全局拦截器阶段生效,在路由到目标后重定向容易逻辑死循环
     * </p>
     * @param uri 新路由
     */
    fun setRedirect(uri: String?): Request {
        if (canRedirect) {
            this.uri = if (uri == null) Uri.EMPTY else Uri.parse(uri)
        } else {
            Logger.e("can not redirect")
        }
        return this
    }

    /**
     * 详细见[Intent.addFlags]
     */
    fun addFlags(flags: Int): Request {
        this.flags = flags or flags
        return this
    }

    /**
     * 详细见[Intent.setFlags]
     */
    fun setFlags(flags: Int): Request {
        this.flags = flags
        return this
    }

    /**
     * 详细见[Intent.setAction]
     */
    fun setAction(action: String): Request {
        this.action = action
        return this
    }

    /**
     * ActivityOptions + Transition方式转场动画.详细见[Context.startActivity]
     */
    fun setOptions(options: ActivityOptionsCompat): Request {
        this.options = options
        return this
    }

    /**
     * 1.设置启动[Activity]时状态回调，默认在启动activity后立即触发callback，且不可修改result数据。
     * 如果需要自定义callback时机（例如在onResume中触发）或设置result数据，需要启用路由hold功能([Route.hold]设为true)，
     * 并在跳转后的activity中调用[RouteHolder.releaseActivity]触发callback。
     *
     * 2.设置[RouteHandler.handle]结果callback。若果result同步返回，直接调用[RouteHandler.setResult]回传结果，
     * 如果结果是异步方式返回，需要开启路由hold功能(设置[Route.hold]为true)并调用[RouteHandler.setResult]回传结果。
     *
     * 3.如果不关心路由执行结果，不调用该方法。
     *
     * @param callback 路由callback，回调总是在UI线程
     */
    fun setRouteCallback(callback: RouteCallback): Request {
        this.routeCallback = callback
        return this
    }

    /**
     * 设置activity启动时[Activity.startActivityForResult]的结果回调，如果不需要监听返回结果不调用该方法
     * @param callback 回调
     */
    fun setActivityResultCallback(callback: ActivityResultCallback<ActivityResult>): Request {
        this.activityResultCallback = callback
        return this
    }

    /**
     * 启动路由
     */
    fun start(activity: FragmentActivity) {
        RouteLauncher(this, activity, activity.lifecycle).launch()
    }

    /**
     * 启动路由
     */
    fun start(fragment: Fragment) {
        RouteLauncher(this, fragment.requireActivity(), fragment.lifecycle).launch()
    }

    /**
     * 启动路由
     * @param context 上下文
     * @param lifecycle 当目标路由没有开启hold功能时该参数无意义。当启用hold功能时lifecycle不应该为空，否则会内存泄漏。
     * 当使用的context是fragmentActivity类型时会使用内嵌的lifecycle，其他类型的context需要开发者传入一个lifecycle
     */
    @JvmOverloads
    fun start(context: Context, lifecycle: Lifecycle? = null) {
        val act = context.getFragmentActivity()
        if (act != null) {
            start(act)
        } else {
            RouteLauncher(this, context, lifecycle).launch()
        }
    }

}